package Simulator;

import java.util.LinkedList;
import java.util.List;

import Shared.MapPosition;
import Shared.Utils;

/**
 * The EnvironmentDatabase module, see Architecture report for specifications.
 */

public class EnvironmentDatabase {

	private List<RealAmbulance> ambs;
	private List<ER> ers;
	private List<MapPosition> hospitals;

	// THE database
	private static final EnvironmentDatabase instance = new EnvironmentDatabase();

	/**
	 * @return The Database singleton
	 */
	public static EnvironmentDatabase getInstance() {
		return instance;
	}

	private EnvironmentDatabase() {
		this.ambs = new LinkedList<RealAmbulance>();
		this.ers = new LinkedList<ER>();
		this.hospitals = new LinkedList<MapPosition>();
	}

	/**
	 * @return the list of all free ambulances
	 */
	synchronized public List<RealAmbulance> getFreeAmbulances() {

		List<RealAmbulance> freeAmbs = new LinkedList<RealAmbulance>();

		for (RealAmbulance current : this.ambs) {
			if (current.isFree())
				freeAmbs.add(current);
		}

		return freeAmbs;
	}

	/**
	 * @return the list of all free equipped ambulances
	 */
	synchronized public List<RealAmbulance> getFreeEquipedAmbulances() {

		List<RealAmbulance> freeAmbs = new LinkedList<RealAmbulance>();

		for (RealAmbulance current : this.ambs) {
			if (current.isFree() && current.isEquiped())
				freeAmbs.add(current);
		}

		return freeAmbs;
	}

	/**
	 * @return the list of all Ambulance
	 */
	synchronized public List<RealAmbulance> getAllAmbulances() {

		return ambs;

	}

	/**
	 * @return true if there exists an equipped ambulance hat is available,
	 *         false otherwise.
	 */
	synchronized public boolean equipedAmbulanceAvailable() {

		for (RealAmbulance current : this.getFreeAmbulances()) {
			if (current.isEquiped())
				return true;
		}

		return false;

	}

	/**
	 * @return the list of all emergencies
	 */
	synchronized public List<ER> getAllER() {

		return ers;

	}

	/**
	 * Add an emergency
	 * 
	 * @param er
	 */
	synchronized public void addER(ER er) {
		ers.add(er);
	}

	/**
	 * Remove every emergency on position mapPosition
	 * 
	 * @param mapPosition
	 *            the position on which to remove emergencies
	 */
	synchronized public void remER(MapPosition mapPosition) {
		if (mapPosition == null) {
			Utils.disp("null er removed");
			return;
		}
		for (ER er : ers) {
			if (er.getLocation().equals(mapPosition)) {
				ers.remove(er);
				return;
			}
		}
	}

	/**
	 * Add an ambulance
	 * 
	 * @param ai
	 *            the ambulance to add
	 */
	synchronized public void addAmb(RealAmbulance ai) {
		ambs.add(ai);
	}

	/**
	 * Remove an ambulance
	 * 
	 * @param ai
	 *            the ambulance to remove
	 */
	synchronized public void remAmb(RealAmbulance ai) {
		ambs.remove(ai);
	}

	/**
	 * Add a hospital on position pos
	 * 
	 * @param pos
	 *            the position on which the new hospital is located
	 */
	synchronized public void addHospital(MapPosition pos) {
		this.hospitals.add(pos);
	}

	/**
	 * @return the list of hospitals
	 */
	synchronized public List<MapPosition> getHospitals() {
		assert this.hospitals.size() > 0;
		return this.hospitals;
	}

	/**
	 * Removes everything from the database.
	 */
	synchronized public void removeAll() {
		this.ambs = new LinkedList<RealAmbulance>();
		this.ers = new LinkedList<ER>();
		this.hospitals = new LinkedList<MapPosition>();
	}

}